import 'dart:async';

import 'package:bluetooth_protocols_plugin/library.dart';
import 'package:flutter/foundation.dart';
import '../../library.dart';
import '../enum/file_traversal_method.dart';
import '../enum/open_file_type.dart';
import '../response/file_response.dart';
import '../tools/utils.dart';
import 'huari_send_helper.dart';

// Huari协议
abstract class HuariProtocol<
        R_INFO extends HuariRealtimeInfo,
        R_STATUS extends HuariRealtimeStatus,
        R_ERROR extends HuariRealtimeError,
        R_ALL extends HuariRealtimeAllInfo,
        R_BATTERY extends HuariRealtimeBatteryInfo,
        S_ONCE extends HuariStatisticsOnceData,
        S_TOTAL extends HuariStatisticsTotalData,
        SET extends HuariSettings,
        INTEGRATED_PRODUCT_INFO extends HuariIntegratedProductionInfo,
        INTEGRATED_R_ALL extends HuariIntegratedRealtimeInfo,
        RSP_DATA extends HuariResponseData> extends HuariSendHelper
    implements
        Protocol<R_INFO, R_STATUS, R_ERROR, R_ALL, R_BATTERY, S_ONCE, S_TOTAL,
            SET, INTEGRATED_PRODUCT_INFO, INTEGRATED_R_ALL, RSP_DATA> {
  @override
  setBluetoothSendMethod(bool status) {
    isBluetoothSendMethod = status; // 设置蓝牙发送方式
  }

  @override
  void setHttpDataProcessor(DataProcessor onMessage) {
    onMessageHttpSent = onMessage; // 设置HTTP发送消息回调
  }

  @override
  Future<RSP_DATA> getAuthRandomCode(Uint8List identifierBytes) {
    debugPrint('获取身份认证随机码');
    // 获取身份认证随机码
    return sendRequest(privateInstrMessage
            .getAuthRandomCodeIntrMsg(identifierBytes)
            .toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Get auth random code failed');
    });
  }

  @override
  Future<RSP_DATA> lock(Uint8List identifierBytes, [bool lock = true]) {
    debugPrint('锁车: $lock');
    // 锁车/解锁
    Uint8List bytes =
        privateInstrMessage.lockIntrMsg(identifierBytes, lock).toBytes();
    return sendRequest(bytes).then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Lock/Unlock failed');
    });
  }

  @override
  Future<RSP_DATA> verifyEncryptRandomNumber(Uint8List random) {
    Uint8List encryptRandom = Utils.int2Uint8List(Utils.calCrc32(random));
    debugPrint('验证加密随机数: $encryptRandom');
    // 验证加密随机数
    Uint8List bytes = privateInstrMessage
        .verifyAuthRandomCodeIntrMsg(encryptRandom)
        .toBytes();
    return sendRequest(bytes).then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Verify encrypt random number failed');
    });
  }

  @override
  Future<RSP_DATA> addMasterKey(
    Uint8List identifierBytes,
    Uint8List masterKey,
  ) {
    debugPrint('写入主密钥: $masterKey');
    // 写入主密钥
    Uint8List bytes = privateInstrMessage
        .addMasterKeyIntrMsg(Uint8List.fromList([
          ...identifierBytes,
          ...masterKey,
        ]))
        .toBytes();
    return sendRequest(bytes).then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Write master key failed');
    });
  }

  @override
  Future<RSP_DATA> deleteMasterKey() {
    debugPrint('删除主密钥');
    // 随机数
    Uint8List random = Uint8List.fromList([0x01, 0x02, 0x03, 0x04]);
    // 加密随机数
    Uint8List encryptRandom = Utils.int2Uint8List(Utils.calCrc32(random));
    // 删除主密钥
    Uint8List bytes = privateInstrMessage
        .deleteMasterKeyIntrMsg(
            Uint8List.fromList([...random, ...encryptRandom]))
        .toBytes();
    return sendRequest(bytes).then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Delete master key failed');
    });
  }

  @override
  Future<RSP_DATA> addSubKey(
    Uint8List identifierBytes,
    Uint8List randomCode,
    Uint8List masterKey,
  ) {
    Uint8List encryptRandom = Utils.int2Uint8List(Utils.calCrc32(randomCode));
    Uint8List keys = Uint8List.fromList(
        List.generate(4, (i) => encryptRandom[i] & masterKey[i]));
    debugPrint('写入子密钥: $keys');
    // 写入子密钥
    Uint8List bytes = privateInstrMessage
        .addSubKeyIntrMsg(Uint8List.fromList([
          ...identifierBytes,
          ...keys,
        ]))
        .toBytes();
    return sendRequest(bytes).then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Write sub key failed');
    });
  }

  @override
  Future<RSP_DATA> getKeyList() {
    debugPrint('获取所有配对密钥id');
    // 随机数
    Uint8List random = Uint8List.fromList([0x01, 0x02, 0x03, 0x04]);
    // 加密随机数
    Uint8List encryptRandom = Utils.int2Uint8List(Utils.calCrc32(random));
    // 拼接获取密钥列表指令
    Uint8List bytes = privateInstrMessage
        .getKeyListIntrMsg(Uint8List.fromList([...random, ...encryptRandom]))
        .toBytes();
    // 获取配对密钥ids
    return sendRequest(bytes).then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Get key List failed');
    });
  }

  @override
  Future<RSP_DATA> deleteSubKey(Uint8List identifierBytes) {
    debugPrint('删除配对密钥: $identifierBytes');
    // 获取配对密钥ids
    return sendRequest(
            privateInstrMessage.deleteSubKeyIntrMsg(identifierBytes).toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Delete paired key by id failed');
    });
  }

  @override
  Future<RSP_DATA> enterNfcCardMode() {
    debugPrint('进入NFC配卡模式');
    // 进入NFC配卡模式
    return sendRequest(privateInstrMessage.enterNfcCardModeIntrMsg().toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Enter nfc card mode failed');
    });
  }

  @override
  Future<RSP_DATA> deleteNfcCard() {
    debugPrint('删除NFC卡');
    // 删除NFC卡
    return sendRequest(privateInstrMessage.deleteNfcCardIntrMsg().toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Delete nfc card failed');
    });
  }

  @override
  Future<RSP_DATA> exitNfcCardMode() {
    debugPrint('退出NFC配卡模式');
    // 退出NFC配卡模式
    return sendRequest(privateInstrMessage.exitNfcCardModeIntrMsg().toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Exit nfc card mode failed');
    });
  }

  @override
  Future<RSP_DATA> writeProductModel(Uint8List bytes) {
    debugPrint('写入产品模型: $bytes');
    return sendRequest(
            privateInstrMessage.writeProductModelIntrMsg(bytes).toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Write product model failed');
    });
  }

  @override
  Future<bool> writeActiveTime(Uint8List time) {
    debugPrint('写入激活时间: $time');
    return sendRequest(
            privateInstrMessage.writeActivationTimeIntrMsg(time).toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!).isSuccess;
      }
      throw Exception('Write active time failed');
    });
  }

  @override
  Future<RSP_DATA> getSn() async {
    debugPrint('获取车辆sn');
    return sendRequest(privateInstrMessage.getSnIntrMsg().toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Get SN failed');
    });
  }

  @override
  Future<bool> setRideMode(int mode) {
    debugPrint('设置骑行模式: $mode');
    return sendRequest(privateInstrMessage.setRideModeIntrMsg(mode).toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!).isSuccess;
      }
      throw Exception('Set ride mode failed');
    });
  }

  @override
  Future<bool> enablePeriodicDataSwitch(bool enable) {
    debugPrint('${enable ? "开启" : "关闭"}周期数据');
    // 开启周期数据开关
    Uint8List bytes =
        privateInstrMessage.enablePeriodicDataSwitchIntrMsg(enable).toBytes();
    return sendRequest(bytes).then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!).isSuccess;
      }
      throw Exception('Enable periodic data switch failed');
    });
  }

  @override
  Future<RSP_DATA> getControllerData(Uint8List addrBytes) {
    debugPrint('读取控制器数据: $addrBytes');
    // 读取控制器曲线
    return sendRequest(
            privateInstrMessage.getControllerDataIntrMsg(addrBytes).toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Get motor controller curve failed');
    });
  }

  @override
  Future<RSP_DATA> setControllerData(Uint8List addrBytes, Uint8List dataBytes) {
    debugPrint('设置控制器数据: $addrBytes, $dataBytes');
    // 设置控制器曲线
    return sendRequest(privateInstrMessage
            .setControllerDataIntrMsg(addrBytes, dataBytes)
            .toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Set controller data failed');
    });
  }

  @override
  Future<List<Map<String, dynamic>>> getFirmwareVersion({
    int? targetDevice,
  }) =>
      throw UnimplementedError();

  @override
  Future<RSP_DATA> getProductModel() {
    debugPrint('获取产品型号');
    return sendRequest(privateInstrMessage.getProductModelIntrMsg().toBytes())
        .then((rspMsg) {
      HuariMessage msg = HuariMessage.fromList(rspMsg);
      if (msg.data != null && msg.data!.toBytes() != null) {
        return HuariResponseData(rsp: msg.data!.toBytes()!) as RSP_DATA;
      }
      throw Exception('Get product model failed');
    });
  }

  @override
  Future<bool> buildSafeConnection() => throw UnimplementedError();

  @override
  Future<bool> setPeriodicDataReportingInterval(int intervalSeconds) =>
      throw UnimplementedError();

  @override
  Future<bool> horn() => throw UnimplementedError();

  @override
  Future<bool> light({required bool lowBeam, required bool highBeam}) =>
      throw UnimplementedError();

  @override
  Future<bool> setStandyTime(int time) => throw UnimplementedError();

  @override
  Future<bool> setVehicleNickname(String nickname) =>
      throw UnimplementedError();

  @override
  Future<bool> setVehiclePassword(String pwd) => throw UnimplementedError();

  @override
  Future<String> getVehicleNickname() => throw UnimplementedError();

  @override
  Future<String> getVehiclePassword() => throw UnimplementedError();

  @override
  Future<bool> clearSearchedTirePressureSensorInfo() =>
      throw UnimplementedError();

  @override
  Future<bool> displayEnterFileTransferStatus(bool enable) =>
      throw UnimplementedError();

  @override
  Future<bool> displayEnterUpgradeStatus(bool enable) =>
      throw UnimplementedError();

  @override
  Future<RSP_DATA> getTirePressureSensorInfo() => throw UnimplementedError();

  @override
  Future<bool> playSound(int audioIndex, {bool? play = true}) =>
      throw UnimplementedError();

  @override
  Future<bool> setAccAndBrakeAssistPercentage(
          int accPercentage, int brakePercentage) =>
      throw UnimplementedError();

  @override
  Future<bool> setAutoHeadlightModeSwitch(bool enabled) =>
      throw UnimplementedError();

  @override
  Future<bool> setBalanceAngle(int angle) => throw UnimplementedError();

  @override
  Future<bool> setBermAngleModeSwitch(bool enabled) =>
      throw UnimplementedError();

  @override
  Future<bool> setDaytimeRunningLightSwitch(bool enabled) =>
      throw UnimplementedError();

  @override
  Future<bool> setDisplayAutoOffSwitch(bool enabled) =>
      throw UnimplementedError();

  @override
  Future<bool> setLogoLightBrightness(int brightness) =>
      throw UnimplementedError();

  @override
  Future<bool> setLowBatteryRideSwitch(bool enabled) =>
      throw UnimplementedError();

  @override
  Future<bool> setMainSoundSwitch(bool enabled) => throw UnimplementedError();

  @override
  Future<bool> setPedalSensitivity(int sensitivity1, int sensitivity2) =>
      throw UnimplementedError();

  @override
  Future<bool> setRideAssistSwitch(bool enabled) => throw UnimplementedError();

  @override
  Future<bool> setRtcTime(DateTime time) => throw UnimplementedError();

  @override
  Future<bool> setSpeedLimit(int speed) => throw UnimplementedError();

  @override
  Future<bool> setSpinKillSwitch(bool enabled) => throw UnimplementedError();

  @override
  Future<bool> setTBoxInfoDisplaySwitch(bool enabled) =>
      throw UnimplementedError();

  @override
  Future<bool> setTBoxLowBatteryWakeupSwitch(bool enabled) =>
      throw UnimplementedError();

  @override
  Future<bool> setTirePressureLowAlarmThreshold(int threshold) =>
      throw UnimplementedError();

  @override
  Future<bool> setTransportModeSwitch(bool enabled) =>
      throw UnimplementedError();

  @override
  Future<bool> setTurnSignalLight({required bool left, required bool right}) =>
      throw UnimplementedError();

  @override
  Future<bool> setVoiceSwitch(bool enabled) => throw UnimplementedError();

  @override
  Future<bool> setVolume(int volume) => throw UnimplementedError();

  @override
  Future<bool> setWarningSpeed(int speed) => throw UnimplementedError();

  @override
  Future<bool> tBoxReboot() => throw UnimplementedError();

  @override
  Future<bool> triggerLoadDetection() => throw UnimplementedError();

  @override
  Future<bool> triggerNoLoadDetection() => throw UnimplementedError();

  @override
  Future<bool> triggerVehicleCalibration(VehicleCalibrationType type) =>
      throw UnimplementedError();

  @override
  Future<VehicleCalibrationStatus> getVehicleCalibrationStatus(
          VehicleCalibrationType type) =>
      throw UnimplementedError();

  @override
  Future<INTEGRATED_PRODUCT_INFO> getIntegratedProductInfo() =>
      throw UnimplementedError();

  @override
  Future<INTEGRATED_R_ALL> getIntegratedRealtimeInfoAll() =>
      throw UnimplementedError();

  @override
  Future<R_ALL> getRealtimeAll() => throw UnimplementedError();

  @override
  Future<R_BATTERY> getRealtimeBatteryInfo() => throw UnimplementedError();

  @override
  Future<R_ERROR> getRealtimeError() => throw UnimplementedError();

  @override
  Future<R_INFO> getRealtimeInfo() => throw UnimplementedError();

  @override
  Future<R_STATUS> getRealtimeStatus() => throw UnimplementedError();

  @override
  Future<SET> getSettingsAll() => throw UnimplementedError();

  @override
  Future<S_ONCE> getStatisticOnce({int? startIndex, int? count}) =>
      throw UnimplementedError();

  @override
  Future<S_TOTAL> getStatisticsTotal() => throw UnimplementedError();

  @override
  Future<bool> clearMotorAdaptationData() => throw UnimplementedError();

  @override
  Future<MotorAutoStatus> getMotorAdaptationStatus() =>
      throw UnimplementedError();

  @override
  Future<bool> startBatteryVoltageCalibration() => throw UnimplementedError();

  @override
  Future<bool> startMotorAdaptation() => throw UnimplementedError();

  @override
  Future<bool> startMotorSelfCheck() => throw UnimplementedError();

  @override
  Future<RSP_DATA> getMotorSelfCheckResult() => throw UnimplementedError();

  @override
  Future<bool> stopMotorAdaptation() => throw UnimplementedError();

  @override
  Future<CloseFileResponse> closeFile(
          TargetDeviceType targetDeviceType, int handle) =>
      throw UnimplementedError();

  @override
  Future<DeleteFileResponse> deleteFile(
          TargetDeviceType targetDeviceType, String path) =>
      throw UnimplementedError();

  @override
  Future<GetFileListResponse> getFileList(
          TargetDeviceType targetDeviceType,
          int index,
          FileTraversalMethod method,
          FileTraversalDepth depth,
          String path,
          String name) =>
      throw UnimplementedError();

  @override
  Future<OpenFileResponse> openFile(
          TargetDeviceType targetDeviceType, OpenFileType type, String path) =>
      throw UnimplementedError();

  @override
  Future<ReadFileInfoResponse> readFileInfo(
          TargetDeviceType targetDeviceType, String path) =>
      throw UnimplementedError();

  @override
  Future<ReadFileResponse> readFile(TargetDeviceType targetDeviceType,
          int handle, int offset, int length) =>
      throw UnimplementedError();

  @override
  Future<WriteFileResponse> writeFile(TargetDeviceType targetDeviceType,
          int handle, int offset, Uint8List data) =>
      throw UnimplementedError();

  @override
  Future<RenameFileResponse> renameFile(
          TargetDeviceType targetDeviceType, String oldPath, String newPath) =>
      throw UnimplementedError();

  @override
  Future<VerifyReadFileResponse> verifyReadFile(
          TargetDeviceType targetDeviceType, int handle, int offset) =>
      throw UnimplementedError();

  @override
  Future<VerifyWriteFileResponse> verifyWriteFile(
          TargetDeviceType targetDeviceType,
          int handle,
          int fileSize,
          int offset,
          int crc32) =>
      throw UnimplementedError();

  @override
  Future<FirmwareUpgradeStatus> queryFirmwareUpdateStatus(
          TargetDeviceType targetDeviceType) =>
      throw UnimplementedError();

  @override
  Future<FirmwareForceUpgradeStatus> queryForceFirmwareUpdateStatus(
          {TargetDeviceType? targetDeviceType}) =>
      throw UnimplementedError();

  @override
  Future<bool> clearForceFirmwareUpdateStatus(
          {TargetDeviceType? targetDeviceType}) =>
      throw UnimplementedError();

  @override
  Future<bool> startFirmwareUpdate(TargetDeviceType targetDeviceType,
          {bool isStart = true}) =>
      throw UnimplementedError();

  @override
  Future<bool> startForceFirmwareUpdate(TargetDeviceType targetDeviceType,
          FirmwareForceUpgradeStatus type, int lowVersion, int highVersion) =>
      throw UnimplementedError();

  @override
  Future<void> startOTA(
    TargetDeviceType targetDeviceType,
    String localFirmwareUrl,
    String newVersion,
    TotalSizeCallback? onTotalSize,
    ProgressCallback onProgress,
    OtaStatusCallback onStatus,
    WaitingUserActionCallback onUserActionRequired, {
    required int maxPacketSize,
  }) =>
      throw UnimplementedError();

  @override
  Future<void> stopOTA(TargetDeviceType targetDeviceType) =>
      throw UnimplementedError();
}
